package com.example.vendingmachine.service.impl;

import com.example.vendingmachine.dto.SlotDTO;
import com.example.vendingmachine.dto.SlotQuery;
import com.example.vendingmachine.entity.Machine;
import com.example.vendingmachine.entity.Slot;
import com.example.vendingmachine.mapper.SlotMapper;
import com.example.vendingmachine.service.MachineService;
import com.example.vendingmachine.service.SlotService;
import com.example.vendingmachine.exception.BusinessException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 货道服务实现类
 */
@Service
@RequiredArgsConstructor
public class SlotServiceImpl implements SlotService {

    private final SlotMapper slotMapper;
    private final MachineService machineService;

    @Override
    public PageInfo<Slot> listSlots(SlotQuery query) {
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        return new PageInfo<>(slotMapper.selectList(query));
    }

    @Override
    public Slot getSlotById(Long id) {
        Slot slot = slotMapper.selectById(id);
        if (slot == null) {
            throw new BusinessException("货道不存在");
        }
        return slot;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createSlot(SlotDTO slotDTO) {
        // 检查设备是否存在且状态为在线
        checkMachine(slotDTO.getMachineId());
        // 检查货道编号是否重复
        checkCodeDuplicate(slotDTO.getCode(), slotDTO.getMachineId(), null);

        Slot slot = new Slot();
        BeanUtils.copyProperties(slotDTO, slot);
        // 设置状态为启用
        slot.setStatus("ENABLED");
        // 设置初始库存为0
        slot.setStock(0);

        slotMapper.insert(slot);
        return slot.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSlot(SlotDTO slotDTO) {
        // 检查货道是否存在
        Slot existSlot = getSlotById(slotDTO.getId());
        
        // 如果更换了设备
        if (!existSlot.getMachineId().equals(slotDTO.getMachineId())) {
            // 检查新设备
            checkMachine(slotDTO.getMachineId());
        }
        
        // 如果修改了编号
        if (!existSlot.getCode().equals(slotDTO.getCode())) {
            // 检查货道编号是否重复
            checkCodeDuplicate(slotDTO.getCode(), slotDTO.getMachineId(), slotDTO.getId());
        }

        Slot slot = new Slot();
        BeanUtils.copyProperties(slotDTO, slot);
        slotMapper.update(slot);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteSlot(Long id) {
        // 检查货道是否存在
        getSlotById(id);
        slotMapper.deleteById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSlotStatus(Long id, String status) {
        // 检查货道是否存在
        getSlotById(id);
        slotMapper.updateStatus(id, status);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSlotStock(Long id, Integer stock) {
        // 检查货道是否存在
        Slot slot = getSlotById(id);
        // 检查库存是否超出容量
        if (stock > slot.getCapacity()) {
            throw new BusinessException("库存不能超过货道容量");
        }
        slotMapper.updateStock(id, stock);
    }

    @Override
    public boolean hasSlotsByMachineId(Long machineId) {
        return slotMapper.countByMachineId(machineId) > 0;
    }

    @Override
    public boolean hasSlotsByProductId(Long productId) {
        return slotMapper.countByProductId(productId) > 0;
    }

    /**
     * 检查设备是否存在且状态为在线
     */
    private void checkMachine(Long machineId) {
        Machine machine = machineService.getMachineById(machineId);
        if (!"ONLINE".equals(machine.getStatus())) {
            throw new BusinessException("所选设备未在线");
        }
    }

    /**
     * 检查货道编号是否重复
     */
    private void checkCodeDuplicate(String code, Long machineId, Long id) {
        Slot existSlot = slotMapper.selectByCodeAndMachineId(code, machineId);
        if (existSlot != null && !existSlot.getId().equals(id)) {
            throw new BusinessException("货道编号已存在");
        }
    }
} 